/*
 * Copyright 2011 www.pretty-tools.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#pragma once

#include <atlsimpcoll.h>
#include "xml/XmlParser.h"
#include "xml/xml_op.h"

class Subscription
{
public:
    CString name;
    CString url;
    CString lastModified;
    CString updateTimeStamp;

    Subscription(LPCTSTR pszName = NULL)
    {
        if (pszName) name = pszName;
    }

    bool operator ! () const 
    {
        return name.IsEmpty();
    }
};

class Subscriptions
{
public:
    CSimpleValArray<Subscription> subscriptions;

    int FindIndexByName(LPCTSTR pszName)
    {
        for (int i = 0; i < subscriptions.GetSize(); ++i)
        {
            if (0 == subscriptions[i].name.CompareNoCase(pszName))
                return i;
        }
        return -1;
    }

    Subscription FindByName(LPCTSTR pszName)
    {
        int idx = FindIndexByName(pszName);

        return idx != -1 ? subscriptions[idx] : Subscription();
    }

    bool LoadFromFile(const CString& strPath)
    {
        if (strPath.IsEmpty())
            return false;

        XML::Parser parser;
        if (parser.ParseFile(strPath))
            parser >> *this;

        return subscriptions.GetSize() > 0;
    }

    bool SaveToFile(const CString& strPath)
    {
        if (strPath.IsEmpty())
            return false;

		CComPtr<IXMLDOMDocument> document;
	    if (FAILED(document.CoCreateInstance( __uuidof(DOMDocument) )))
		    return false;

		CComPtr<IXMLDOMElement> root;
	    if (FAILED(document->createElement(CComBSTR(L"subscriptions"), &root)))
		    return false;

	    document->appendChild(root, &CComPtr<IXMLDOMNode>());

        for (int i = 0; i < subscriptions.GetSize(); ++i)
        {
	        CComPtr<IXMLDOMElement> elem;
	        if (FAILED(document->createElement(CComBSTR(L"subscription"), &elem)))
		        return false;

            if (!AddAttribute(document, elem, L"name", subscriptions[i].name))
                return false;
            if (!AddAttribute(document, elem, L"url", subscriptions[i].url))
                return false;
            if (!AddAttribute(document, elem, L"lastModified", subscriptions[i].lastModified))
                return false;
            if (!AddAttribute(document, elem, L"updateTimeStamp", subscriptions[i].updateTimeStamp))
                return false;

            root->appendChild(elem, &CComPtr<IXMLDOMNode>());
        }

        CComBSTR bsXML;
        if (FAILED(root->get_xml(&bsXML)))
            return false;

        CStringA strXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
        strXML += EncodeToUTF8(bsXML);

        File f;
        if (f.Create(strPath))
            f.Write((LPCSTR)strXML, strXML.GetLength());

        return true;
    }

private:
    bool AddAttribute(CComPtr<IXMLDOMDocument>& document, CComPtr<IXMLDOMElement>& elem, LPCWSTR pszName, LPCWSTR pszValue)
    {
        if (!pszValue || !*pszValue)
            return true;

        CComPtr<IXMLDOMAttribute> attr;
        if (FAILED(document->createAttribute(CComBSTR(pszName), &attr)))
            return false;

        if (FAILED(attr->put_value(CComVariant(pszValue))))
            return false;

        if (FAILED(elem->setAttributeNode(attr, &CComPtr<IXMLDOMAttribute>())))
            return false;

        return true;
    }
};

XML_SERIALIZE_MAP(Subscription)
    XML_MAP_ATTRIBUTE(name)
    XML_MAP_ATTRIBUTE(url)
    XML_MAP_ATTRIBUTE(lastModified)
    XML_MAP_ATTRIBUTE(updateTimeStamp)
XML_END_SERIALIZE_MAP()

XML_SERIALIZE_MAP(Subscriptions)
    XML_MAP_ELEMENT2("subscription", subscriptions)
XML_END_SERIALIZE_MAP()
